package com.fsm.utils;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import redis.clients.jedis.Jedis;

/**
 * 错误锁方式A
 */
public class WrongARedisDLock  {
    private static final Logger LOG = LogManager.getLogger(WrongARedisDLock.class);
    private final String lockName;
    private final int lockDuration;
    private final String lockSubject;
    private final Jedis jedis;

    public WrongARedisDLock(String lockName, int lockDuration, String lockSubject, Jedis jedis) {
        this.lockName = lockName;
        this.lockDuration = lockDuration;
        this.lockSubject = lockSubject;
        this.jedis = jedis;
    }
    public void lock() {
        tryLock(Long.MAX_VALUE);
    }
    public boolean tryLock() {
        return tryLock(0);
    }
    public boolean tryLock(long waitTimeout) {
        long startTime = System.currentTimeMillis();
        while (true) {
            try {
                // 设置锁名和锁申请主体的唯一标识
                if (jedis.setnx(lockName, lockSubject) != null) {
                    // 若此时程序故障退出，锁将无法释放
                    jedis.expire(lockName, lockDuration);
                    return true;
                }
                String lockOwner = jedis.get(lockName);
                if (lockSubject.equals(lockOwner)) {
                    return true;
                }
                if (lockOwner == null) {
                    continue;
                }
                if (System.currentTimeMillis() - startTime < waitTimeout) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException ie) {
                    }
                    continue;
                }
                return false;
            } catch (Exception e) {
                LOG.error("tryLock error", e);
                if (System.currentTimeMillis() - startTime < waitTimeout) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException ie) {
                    }
                    continue;
                }
                return false;
            }
        }
    }

    public void unlock() {
        try {
            String lockOwner = jedis.get(lockName);
            if (lockSubject.equals(lockOwner)) {
                // 若此时锁过期了并且被其它申请者成功获取，则将误删锁
                jedis.del(lockName);
            }
        } catch (Exception e) {
            LOG.error("unlock error", e);
        }
    }
}